<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html>
<head>
<title>Widgets II in wxWidgets</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="wxWidgets, tutorial, widgets, C++, programming, GUI, multiplatform">
<meta name="description" content="This part of the wxWidgets tutorial continues covering widgets.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">
</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>


<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Widgets II</h1>


<p>
In this chapter, we will continue introducing various other widgets. 
We will mention <code>wxListBox</code>, <code>wxNotebook</code> and
<code>wxScrolledWindow</code>.
</p>

<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* NewSquare */
google_ad_slot = "0364418177";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 


<h2>wxListBox</h2>

<p>
A wxListBox widget is used for displaying and working with a list 
of items. As it's name indicates, it is a rectangle that has a list 
of strings inside. We could use it for displaying a list of mp3 files, 
book names, module names of a larger project or names of our friends. 
A wxListBox can be created in two different states. In a single 
selection state or a multiple selection state. The single selection 
state is the default state. There are two significant events in 
wxListBox. The first one is the wxEVT_COMMAND_LISTBOX_SELECTED event. 
This event is generated when we select a string in a wxListBox. The 
second one is the wxEVT_COMMAND_LISTBOX_DOUBLE_CLICKED event. It is 
generated when we double click an item in a wxListBox. The number of 
elements inside a wxListBox is limited on GTK platform. According to 
the documentation, it is currently around 2000 elements. The elements 
are numbered from zero. Scrollbars are displayed automatically if needed.
</p>

<div class="codehead">Listbox.h</div>
<pre class="code">
#include &lt;wx/wx.h&gt;
#include &lt;wx/listbox.h&gt;

class MyPanel : public wxPanel
{
public:
    MyPanel(wxPanel *parent);

    void OnNew(wxCommandEvent&amp; event);
    void OnRename(wxCommandEvent&amp; event);
    void OnClear(wxCommandEvent&amp; event);
    void OnDelete(wxCommandEvent&amp; event);

    wxListBox *m_lb;

    wxButton *m_newb;
    wxButton *m_renameb;
    wxButton *m_clearb;
    wxButton *m_deleteb;

};

class Listbox : public wxFrame
{
public:
    Listbox(const wxString&amp; title);

    void OnDblClick(wxCommandEvent&amp; event);

    wxListBox *listbox;
    MyPanel *btnPanel;

};

const int ID_RENAME = 1;
const int ID_LISTBOX = 5;
</pre>

<div class="codehead">Listbox.cpp</div>
<pre class="code">
#include "listbox.h"
#include &lt;wx/textdlg.h&gt;


Listbox::Listbox(const wxString&amp; title)
       : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(270, 200))
{

  wxPanel * panel = new wxPanel(this, -1);

  wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL);

  listbox = new wxListBox(panel, ID_LISTBOX, 
      wxPoint(-1, -1), wxSize(-1, -1)); 

  hbox->Add(listbox, 3, wxEXPAND | wxALL, 20);

  btnPanel = new MyPanel(panel);
  hbox->Add(btnPanel, 2, wxEXPAND | wxRIGHT, 10);

  Connect(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, 
      wxCommandEventHandler(Listbox::OnDblClick));

  panel->SetSizer(hbox);
  Center();  
}


MyPanel::MyPanel(wxPanel * parent)
       : wxPanel(parent, wxID_ANY)
{
  wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);

  Listbox *lb = (Listbox *) parent->GetParent();
  m_lb = lb->listbox;

  m_newb = new wxButton(this, wxID_NEW, wxT("New"));
  m_renameb = new wxButton(this, ID_RENAME, wxT("Rename"));
  m_deleteb = new wxButton(this, wxID_DELETE, wxT("Delete"));
  m_clearb = new wxButton(this, wxID_CLEAR, wxT("Clear"));

  Connect(wxID_NEW, wxEVT_COMMAND_BUTTON_CLICKED, 
      wxCommandEventHandler(MyPanel::OnNew) );
  Connect(ID_RENAME, wxEVT_COMMAND_BUTTON_CLICKED, 
      wxCommandEventHandler(MyPanel::OnRename) );
  Connect(wxID_CLEAR, wxEVT_COMMAND_BUTTON_CLICKED, 
      wxCommandEventHandler(MyPanel::OnClear) );
  Connect(wxID_DELETE, wxEVT_COMMAND_BUTTON_CLICKED, 
      wxCommandEventHandler(MyPanel::OnDelete) );

  vbox->Add(-1, 20);
  vbox->Add(m_newb);
  vbox->Add(m_renameb, 0, wxTOP, 5);
  vbox->Add(m_deleteb, 0, wxTOP, 5);
  vbox->Add(m_clearb, 0, wxTOP, 5);

  SetSizer(vbox);
 
}


void MyPanel::OnNew(wxCommandEvent&amp; event) 
{
  wxString str = wxGetTextFromUser(wxT("Add new item"));
  if (str.Len() > 0)
      m_lb->Append(str); 
}

void MyPanel::OnClear(wxCommandEvent&amp; event) 
{
  m_lb->Clear();
}

void MyPanel::OnRename(wxCommandEvent&amp; event) 
{
  wxString text;
  wxString renamed;
  
  int sel = m_lb->GetSelection();
  if (sel != -1) {
      text = m_lb->GetString(sel);
      renamed = wxGetTextFromUser(wxT("Rename item"), 
                  wxT("Rename dialog"), text);
  }

  if (!renamed.IsEmpty()) {
      m_lb->Delete(sel);
      m_lb->Insert(renamed, sel);
  }
}


void MyPanel::OnDelete(wxCommandEvent&amp; event) 
{
  int sel = m_lb->GetSelection();
  if (sel != -1) {
      m_lb->Delete(sel);
  }
}


void Listbox::OnDblClick(wxCommandEvent&amp; event) 
{
  wxString text;
  wxString renamed;

  int sel = listbox->GetSelection();
  if (sel != -1) {
      text = listbox->GetString(sel);
      renamed = wxGetTextFromUser(wxT("Rename item"), 
                  wxT("Rename dialog"), text);
  } 

  if (!renamed.IsEmpty()) {
      listbox->Delete(sel);
      listbox->Insert(renamed, sel);
  }
}
</pre>

<div class="codehead">main.h</div>
<pre class="code">
#include &lt;wx/wx.h&gt;

class MyApp : public wxApp
{
  public:
    virtual bool OnInit();
};
</pre>

<div class="codehead">main.cpp</div>
<pre class="code">
#include "main.h"
#include "Listbox.h"

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{

    Listbox *listbox = new Listbox(wxT("Listbox"));
    listbox->Show(true);

    return true;
}
</pre>

<pre class="explanation">
listbox = new wxListBox(panel, ID_LISTBOX, 
    wxPoint(-1, -1), wxSize(-1, -1));
</pre>

<p>
This is the constructor of the listbox widget.
</p>

<p>
In our example, we have a list box and four buttons. The buttons are 
used to add, rename, delete and clear all items in 
the listbox.
</p>

<pre class="explanation">
wxString str = wxGetTextFromUser(wxT("Add new item"));
if (str.Len() > 0)
    m_lb->Append(str); 
</pre>

<p>
To add a new string to the listbox, we display a <i>wxGetTextFromUser</i> 
dialog. We call the <i>Append()</i> method to 
append string to the listbox.
</p>

<pre class="explanation">
m_lb->Clear();
</pre>

<p>
To clear all items is the easiest action to do. We just call the <i>Clear()</i> method.
</p>

<pre class="explanation">
int sel = m_lb->GetSelection();
if (sel != -1) {
    m_lb->Delete(sel);
}
</pre>

<p>
To delete an item, we figure out the selected item. Then we call 
the <i>Delete()</i> method.
</p>

<p>
Renaming an item requires several steps.
</p>

<pre class="explanation">
wxString text;
wxString renamed;
</pre>

<p>
We define two local variables.
</p>

<pre class="explanation">
int sel = listbox->GetSelection();
if (sel != -1) {
    text = listbox->GetString(sel);
    renamed = wxGetTextFromUser(wxT("Rename item"), 
                wxT("Rename dialog"), text);
} 
</pre>

<p>
We get the selected string and save it to the renamed variable.
</p>

<pre class="explanation">
if (!renamed.IsEmpty()) {
    m_lb->Delete(sel);
    m_lb->Insert(renamed, sel);
}
</pre>

<p>
We check whether the renamed variable is empty. This is to avoid 
inserting empty strings. Then we delete the old item and
insert a new one.
</p>

<img src="/img/gui/wxwidgets/listbox.jpg" alt="Listbox">
<div class="figure">Figure: Listbox </div>


<h2>wxNotebook</h2>

<p>
wxNotebook widget joins multiple windows with corresponding tabs. 
You can position the Notebook widget using the following style flags: 
</p>

<ul>
<li>wxNB_LEFT</li>
<li>wxNB_RIGHT</li> 
<li>wxNB_TOP</li> 
<li>wxNB_BOTTOM</li> 
</ul>

<p>
The default position is wxNB_TOP.
</p>


<div class="codehead">Notebook.h</div>
<pre class="code">
#include &lt;wx/wx.h&gt;
#include &lt;wx/notebook.h&gt;
#include &lt;wx/grid.h&gt;

class Notebook : public wxFrame
{
public:
    Notebook(const wxString&amp; title);

    void OnQuit(wxCommandEvent&amp; event);

};


class MyGrid : public wxGrid
{
public:
    MyGrid(wxNotebook *parent);

};
</pre>

<div class="codehead">Notebook.cpp</div>
<pre class="code">
#include "Notebook.h"

Notebook::Notebook(const wxString&amp; title)
       : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(400, 350))
{

  wxNotebook *nb = new wxNotebook(this, -1, wxPoint(-1, -1), 
      wxSize(-1, -1), wxNB_BOTTOM);

  wxMenuBar *menubar = new wxMenuBar;
  wxMenu *file = new wxMenu;
  file->Append(wxID_EXIT, wxT("Quit"), wxT(""));
  menubar->Append(file, wxT("&amp;File"));
  SetMenuBar(menubar);

  Connect(wxEVT_COMMAND_MENU_SELECTED, 
      wxCommandEventHandler(Notebook::OnQuit)); 

  MyGrid *grid1 = new MyGrid(nb);
  MyGrid *grid2 = new MyGrid(nb);
  MyGrid *grid3 = new MyGrid(nb);

  nb->AddPage(grid1, wxT("Sheet1"));
  nb->AddPage(grid2, wxT("Sheet2"));
  nb->AddPage(grid3, wxT("Sheet3"));

  CreateStatusBar();
  Center();
}


void Notebook::OnQuit(wxCommandEvent&amp; event) 
{
  Close(true);
}

MyGrid::MyGrid(wxNotebook * parent)
       : wxGrid(parent, wxID_ANY)
{
  CreateGrid(30, 30);
  SetRowLabelSize(50);
  SetColLabelSize(25);
  SetRowLabelAlignment(wxALIGN_RIGHT, wxALIGN_CENTRE);
  SetLabelFont(wxFont(9, wxFONTFAMILY_DEFAULT, 
      wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD));

  for (int i = 0; i &lt; 30 ; i++) {
      this->SetRowSize(i, 25);
  }
}
</pre>

<div class="codehead">main.h</div>
<pre class="code">
#include &lt;wx/wx.h&gt;

class MyApp : public wxApp
{
  public:
    virtual bool OnInit();
};
</pre>

<div class="codehead">main.cpp</div>
<pre class="code">
#include "main.h"
#include "Notebook.h"

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{

    Notebook *notebook = new Notebook(wxT("Notebook"));
    notebook->Show(true);

    return true;
}
</pre>


<p>
In this example, we have created a notebook widget with three grids. 
The notebook widget is positioned at the 
bottom.
</p>


<pre class="explanation">
wxNotebook *nb = new wxNotebook(this, -1, wxPoint(-1, -1), 
    wxSize(-1, -1), wxNB_BOTTOM);
</pre>

<p>
Here we create the notebook widget. 
</p>

<pre class="explanation">
nb->AddPage(grid1, wxT("Sheet1"));
nb->AddPage(grid2, wxT("Sheet2"));
nb->AddPage(grid3, wxT("Sheet3"));
</pre>

<p>
We add three grid objects into the notebook widget. 
</p>

<img src="/img/gui/wxwidgets/notebook.png" alt="Notebook">
<div class="figure">Figure: Notebook widget </div>


<h2>wxScrolledWindow</h2>

<p>
This is one of the container widgets. It can be useful, when we have a 
larger area than a window can display. In our example, we demonstrate 
such a case. We place a large image into our window. When the window 
is smaller than our image, Scrollbars are displayed automatically.
</p>

<div class="codehead">scrolledwindow.h</div>
<pre class="code">
#include &lt;wx/wx.h&gt;

class ScrWindow : public wxFrame
{
public:
  ScrWindow(const wxString&amp; title);

};
</pre>

<div class="codehead">scrolledwindow.cpp</div>
<pre class="code">
#include "scrolledwindow.h"

ScrWindow::ScrWindow(const wxString&amp; title)
       : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(300, 200))
{
  wxImage::AddHandler(new wxJPEGHandler);
  wxScrolledWindow *sw = new wxScrolledWindow(this);
  
  wxBitmap bmp(wxT("castle.jpg"), wxBITMAP_TYPE_JPEG);
  wxStaticBitmap *sb = new wxStaticBitmap(sw, -1, bmp);

  int width = bmp.GetWidth();
  int height = bmp.GetHeight();

  sw->SetScrollbars(10, 10, width/10, height/10);
  sw->Scroll(50,10);

  Center();
}
</pre>

<div class="codehead">main.h</div>
<pre class="code">
#include &lt;wx/wx.h&gt;

class MyApp : public wxApp
{
  public:
    virtual bool OnInit();
};

</pre>

<div class="codehead">main.cpp</div>
<pre class="code">
#include "main.h"
#include "scrolledwindow.h"

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{

    ScrWindow *sw = new ScrWindow(wxT("ScrolledWindow"));
    sw->Show(true);

    return true;
}
</pre>

<p>
In our example, we display a picture of a Spis castle. 
</p>

<pre class="explanation">
wxImage::AddHandler(new wxJPEGHandler);
</pre>

<p>
To handle jpg images, we must initiate the <i>wxJPEGHandler</i>.
</p>

<pre class="explanation">
wxScrolledWindow *sw = new wxScrolledWindow(this);

wxBitmap bmp(wxT("castle.jpg"), wxBITMAP_TYPE_JPEG);
wxStaticBitmap *sb = new wxStaticBitmap(sw, -1, bmp);
</pre>

<p>
We create a scroll window and put a static bitmap into it.
</p>

<pre class="explanation">
sw->SetScrollbars(10, 10, width/10, height/10);
</pre>

<p>
We set the scrollbars. 
</p>

<pre class="explanation">
sw->Scroll(50,10);
</pre>

<p>
We scroll the window a bit.
</p>

<p>
In this chapter, we continued covering widgets in wxWidgets library.
</p>

<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br>



<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified December 10, 2008  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>
